#ifndef __MVOS_APIS_H__
#define __MVOS_APIS_H__

#include "mvdef.h"

MVCXX_EXTERN_BEGIN

/********************************/
/** CMake自动根据编译环境生成定义 */
///< 特殊的64位可变参入参适配机制（部分编译器对64位可变参入参兼容性异常，mvos的部分接口需要这里额外适配处理）
/* #undef MV_VA_ARG_SPEC_ALIGN_64 */
/********************************/

#define MVOS_APIS_VER      5 ///<标识API非兼容级别改动，每次非兼容版本改动+1
/**
 * @brief mvos系统适配api库非兼容版本校验接口
 * 
 * @param [in] s32_api_ver : MVOS_APIS_VER
 * @return 校验结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_ABORT
 * @note 建议调用，确保兼容性问题能在开发过程中发现
 */
mv_s32_t MVAPI mvos_apis_ver_check(mv_s32_t s32_api_ver);

#define MVOS_PATH_MAX_LEN  256

/*****************************************
 *            fd类文件句柄操作
 *****************************************/
typedef enum _open_flag
{
    /* s32_o_flags */
    MVOS_O_RDONLY   = 00,
    MVOS_O_WRONLY   = 01,
    MVOS_O_RDWR     = 02,
    MVOS_O_CREAT    = 0100,
    MVOS_O_TRUNC    = 01000,
    MVOS_O_APPEND   = 02000,
    MVOS_O_NONBLOCK = 04000,
    MVOS_O_CLOEXEC  = 010000000, /* set close_on_exec */
}mvos_open_flag_e;
typedef enum _file_mode
{
    /* s32_f_mode */
    MVOS_F_OK     =  00,
    MVOS_F_XOK    =  01,
    MVOS_F_WOK    =  02,
    MVOS_F_ROK    =  04,

    MVOS_FFMT     =  0xf,
}mvos_file_mode_e;
typedef enum _trunc_mode
{
    MVOS_T_SET    =  0,
    MVOS_T_DEC    =  1,
    MVOS_T_INC    =  2,
}mvos_trunc_mode_e;
mv_s32_t   MVAPI mvos_open(mv_cv8ptr_t cpv8_path,   mv_s32_t s32_o_flags, mv_s32_t s32_f_mode);
/**
 *  MV_EC_SUCCESS: all requested @s32_f_flags granted;
 *  MV_EC_FAILED:  at least one bit in @s32_f_flags asked for a permission that  is  denied;
 */
mv_s32_t   MVAPI mvos_access(mv_cv8ptr_t cpv8_path, mv_s32_t s32_f_mode);
mv_s32_t   MVAPI mvos_remove(mv_cv8ptr_t cpv8_path);
mv_s32_t   MVAPI mvos_rename(mv_cv8ptr_t cpv8_old_path, mv_cv8ptr_t cpv8_new_path);
mv_s32_t   MVAPI mvos_truncate(mv_cv8ptr_t cpv8_path, mv_off_t off, mv_s32_t s32_t_mode);
/*********/
#define MVOS_SEEK_SET   0
#define MVOS_SEEK_CUR   1
#define MVOS_SEEK_END   2
mv_off_t   MVAPI mvos_lseek(mv_s32_t fd, mv_off_t offset,   mv_s32_t s32_whence);
mv_ssize_t MVAPI mvos_read (mv_s32_t fd, mv_vptr_t p_buf,   mv_size_t sz_count);
mv_ssize_t MVAPI mvos_write(mv_s32_t fd, mv_cvptr_t cp_buf, mv_size_t sz_count);
mv_s32_t   MVAPI mvos_close(mv_s32_t fd);
mv_s32_t   MVAPI mvos_sync (mv_s32_t fd);
mv_s32_t   MVAPI mvos_cpfile(mv_cv8ptr_t cpv8_source, mv_cv8ptr_t cpv8_dest);
/** "mvos_file_read" 和 "mvos_file_write" 文件不存在会导致操作失败 */
mv_ssize_t MVAPI mvos_file_read (mv_cv8ptr_t cpv8_file, mv_off_t offset, mv_vptr_t   p_buf, mv_size_t sz_count);
mv_ssize_t MVAPI mvos_file_write(mv_cv8ptr_t cpv8_file, mv_off_t offset, mv_cvptr_t cp_buf, mv_size_t sz_count);
/**
 * @brief 单次读取目标文件指定范围数据（"mvos_file_read"进阶安全版API）
 * 
 * @param cpv8_file  [in] 目标文件路径
 * @param offset     [in] 起始位置偏移
 * @param ppv8_cache [in] 读出内容缓存地址指针
 * @param sz_maxlen  [in] 读出内容缓存地址最大容量
 * @param sz_count   [in] 目标读出内容长度（特别的，支持 0 入参，表示从指定起始位置开始读取到文件结尾）
 * @return 操作结果
 * - success : 实际读出内容长度
 * -  failed : MV_EC_INVALID_ARGS  (ppv8_cache为NULL异常) <br/>
 *             MV_EC_MALLOC_FAILED (内存不足，【智能内存申请】时) <br/>
 *             MV_EC_FAILED        (通用失败：文件不存在、打开失败、读取失败等)
 * @note ppv8_cache入参实体指向可以为NULL,且sz_maxlen为0时，代表启用【智能内存申请】机制，<br/>
 *       自动申请满足的缓存长度内容，并赋值ppv8_cache出参;<br/>
 *         e.g. mv_vptr_t p = NULL; mvos_file_read_sp(path, 0, &p, 0, 100);<br/>
 *       sz_maxlen为非0时，代表普通模式，ppv8_cache应为实体地址，使用(mv_v8ptr_t*)方式进行异变传参，以符合调用方法；<br/>
 *         e.g. mv_v8_t av8_buf[16] = {0}; mvos_file_read_sp(path, 0, (mv_v8ptr_t*)av8_buf, 16, 10);，<br/>
 * @note 使用【智能内存申请】机制后，调用者须在不再需要使用的时候，自行释放该内存块，避免内存泄露！
 * @note 使用【智能内存申请】机制输出的缓冲区，有额外1字节的结束符安全位，可以放心使用
 */
mv_ssize_t MVAPI mvos_file_read_sp(mv_cv8ptr_t cpv8_file, mv_off_t offset, mv_v8ptr_t *ppv8_cache, mv_size_t sz_maxlen, mv_size_t sz_count);

/**
 * @brief 路径解析（拆分 目录名 和 文件名）
 * 
 * @param pv8_path      [in] 目标路径
 * @param ppv8_basename [out]取出文件名缓存地址(可选，入参为NULL则不提取)
 * @return 目录名（不带'/'结尾）
 * - success : 目录名缓存地址
 * -  failed : NULL
 * @attention 注意，成功解析后，在不需要使用时，应及时释放目录名缓存地址，否则会导致内存泄漏 !!!
 */
mv_v8ptr_t MVAPI mvos_pathname(mv_v8ptr_t pv8_path, mv_v8_t **ppv8_basename);

/**
 * @brief 对FD可读写状态等待及查询
 * 
 * @param s32_fd         [in] 目标FD（可以是文件fd、socketfd等支持状态查询的fd）
 * @param s16_event      [in] 等待事件状态类型bitmap（MVOS_FDE_XXX）
 * @param s32_timeout_ms [in] 等待超时时间
 * @param pu8_runflag    [in] 运行标识（用于强制打断；0=中断；else=等待；可以为NULL）
 * @return 目录名（不带'/'结尾）
 * - success : MV_EC_SUCCESS (目标状态Ready)
 * -  failed : MV_EC_IO_ERROR(fd状态异常)
 *             MV_EC_TIMEOUT (目标状态等待超时)
 * @attention 注意，成功解析后，在不需要使用时，应及时释放目录名缓存地址，否则会导致内存泄漏 !!!
 */
#define MVOS_FDE_POLLIN    0x001    /* There is data to read.  */
#define MVOS_FDE_POLLPRI   0x002    /* There is urgent data to read.  */
#define MVOS_FDE_POLLOUT   0x004    /* Writing now will not block.  */
mv_s32_t MVAPI mvos_poll(mv_s32_t s32_fd, mv_s16_t s16_fde_event, mv_s32_t s32_timeout_ms, mv_u8ptr_t pu8_runflag);
/*****************************************
 *              dir类操作
 *****************************************/
#define MVOS_D_XOK      01
#define MVOS_D_WOK      02
#define MVOS_D_ROK      04
/* will automatically make all directories in path that required */
/* path max len = 256 */
/**
 * @brief 文件夹（递归）创建操作
 * 
 * @param cpv8_path   [in] 目标目录路径
 * @param u32_d_flags [in] DIR属性flags [MVOS_D_XOK, MVOS_D_WOK, MVOS_D_ROK]
 * @param bl_smart    [in] MV_FALSE=传统模式(每一级目录以'/'为分割), MV_TRUE=智能模式(最后一级目录不强制以'/'结束)
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_FAILED
 * @note 传统模式: 仅检查识别'/'为标识的每一段目录路径;<br/>
 *         e.g. /tmp/test/123 -> /tmp/ + /tmp/test/ 两个目录创建 <br/>
 *       智能模式: 当输入路径没有以'/'结尾时，也会自动当做合法目录路径进行创建 <br/>
 *         e.g. /tmp/test/123 -> /tmp/ + /tmp/test/ + /tmp/test/123/ 三个目录创建 <br/>
 *       请自行根据实际选择合适的模式!
 */
mv_s32_t MVAPI mvos_mkdir(mv_cv8ptr_t cpv8_path, mv_u32_t u32_d_flags, mv_bool_t bl_smart);
#define MVOS_DFMT        0xff0
#define MVOS_DT_UNKNOWN  0
#define MVOS_DT_SOCK     0x200
#define MVOS_DT_LNK      0x100
#define MVOS_DT_FILE     0x080
#define MVOS_DT_DIR      0x040
#define MVOS_DT_DEV      0x020
#define MVOS_DT_FIFO     0x010
#define MVOS_SCAN_T2B    0 ///< TOP TO BOTTOM, support ignore of DT_DIR result to not to dive in subdir
#define MVOS_SCAN_B2T    1 ///< BOTTOM TO TOP
/**
 * @brief 文件夹递归遍历
 * 
 * @param cpv8_path    [in] 目标根目录
 * @param u8_deep      [in] 递归深度
 * @param u8_scan_mode [in] 遍历模式 [MVOS_SCAN_T2B / MVOS_SCAN_B2T]
 * @param f_on_result  [in] 遍历结果回调
 * @param p_usr_data   [in] 回调用户数据
 * @return 遍历操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_NOT_FOUND      (文件夹不存在)
 *             MV_EC_IGNORE        （路径类型非文件夹）
 *             MV_EC_MALLOC_FAILED （申请内存失败）
 *             else
 */
mv_s32_t MVAPI mvos_dir(mv_cv8ptr_t cpv8_path, mv_u8_t u8_deep, mv_u8_t u8_scan_mode, mv_s32_t(*f_on_result)(mv_v8_t av8_path[256], mv_v8_t av8_name[256], mv_u16_t u16_dt_type, mv_vptr_t p_usr_data), mv_vptr_t p_usr_data);
#define MVOS_DM_NORMAL  0
#define MVOS_DM_ROUTE   1
/** MV_EC_SUCCESS: empty; else: not empty or some err */
mv_s32_t MVAPI mvos_dir_isempty(mv_cv8ptr_t cpv8_path);
/** 0: not remove if not empty; 1: remove all in route */
mv_s32_t MVAPI mvos_rmdir(mv_cv8ptr_t cpv8_path,   mv_u8_t     u8_dm_mode);
/** src和dst均需要带/结尾，作用就是把src目录下所有内容，拷贝到dst目录下 */
mv_s32_t MVAPI mvos_cpdir(mv_cv8ptr_t cpv8_source, mv_cv8ptr_t cpv8_dest);

/**
 * @brief fd&dir复合类操作
 */
typedef struct _stat {
    mv_u32_t   u32_ftype;    ///< FStype(dir only)
    mv_s32_t   s32_mode;     ///< DT(type) & F(mode)
    mv_size_t  sz_total;     ///< Total size, in bytes
    mv_size_t  sz_free;      ///< Free  size, in bytes (dir only)
    mv_size_t  sz_blksize;   ///< Prefer block size for filesystem I/O
    mv_time_t  ts_access;    ///< Time of last access
    mv_time_t  ts_modify;    ///< Time of last modification
    mv_time_t  ts_change;    ///< Time of last status change
}mvos_stat_t;
/**
 * @brief 目标状态信息获取
 * 
 * @param cpv8_path [in] 目标路径
 * @param pstat    [out] 状态信息结构存储地址
 * @return 获取操作结果
 * -  success : MV_EC_SUCCESS
 * -   failed : MV_EC_INVALID_ARGS
 *              MV_EC_NOT_FOUND
 *              MV_EC_FAILED
 */
mv_s32_t MVAPI mvos_stat (mv_cv8ptr_t cpv8_path, mvos_stat_t *pstat);

#if 0
/**
 * @brief socket类句柄操作
 */
#define MVOS_SHUT_RD    0
#define MVOS_SHUT_WR    1
#define MVOS_SHUT_RDWR  2
mv_s32_t MVAPI mvos_shutdown(mv_s32_t fd, mv_s32_t s32_how);
#endif

/*****************************************
 *         net interface类操作
 *****************************************/
typedef enum _net_interface_flag
{
    MVOS_NIF_INVALD    = 0x0,
    MVOS_NIF_IPV4      = 0x1,
    MVOS_NIF_NETMASK   = 0x2,
    MVOS_NIF_GATEWAY   = 0x4,
    MVOS_NIF_DNS_MAJOR = 0x8,
    MVOS_NIF_DNS_MINOR = 0x10,

    MVOS_NET_ALL   = (MVOS_NIF_IPV4 | MVOS_NIF_NETMASK | MVOS_NIF_GATEWAY | MVOS_NIF_DNS_MAJOR | MVOS_NIF_DNS_MINOR),
}mvos_nif_flag_e;

#define MVOS_NET_BUFLEN   16
#define MVOS_IPV6_BUFLEN  46

typedef struct _net_interface_info
{
    mv_s32_t s32_flag;
    mv_v8ptr_t pv8_dns_path;
    /**
     * @brief 指定格式：非空，则按照此格式填充结果，否则，按原始类型填充
     * @note  全统一，且注意适用4段格式来匹配，以及hhu的变量类型准确性使用 \n 
     *        如: "%hhu.%hhu.%hhu.%hhu" 
     * @note  union的u32类型可用于无格式时的数据访问（避免编译器strict-aliasing警告问题）
     */
    mv_v8ptr_t pv8_fmt;

    union {
        mv_u32_t u32_ipv4;
        mv_v8_t  av8_ipv4[MVOS_NET_BUFLEN];
    };
    union {
        mv_u32_t u32_netmask;
        mv_v8_t  av8_netmask[MVOS_NET_BUFLEN];
    };
    union {
        mv_u32_t u32_getway;
        mv_v8_t  av8_gateway[MVOS_NET_BUFLEN];
    };
    union {
        mv_u32_t u32_dns_major;
        mv_v8_t  av8_dns_major[MVOS_NET_BUFLEN];
    };
    union {
        mv_u32_t u32_dns_minor;
        mv_v8_t  av8_dns_minor[MVOS_NET_BUFLEN];
    };
}mvos_nif_info_t;

mv_s32_t MVAPI mvos_nif_info_get(mv_v8ptr_t pv8_ifname, mvos_nif_info_t *p);
mv_s32_t MVAPI mvos_nif_info_set(mv_v8ptr_t pv8_ifname, mvos_nif_info_t *p);
mv_s32_t MVAPI mvos_nif_mac_get(mv_v8ptr_t pv8_ifname, mv_v8_t av8_mac[24], mv_v8ptr_t pv8_fmt);
mv_s32_t MVAPI mvos_nif_info_clear(mv_v8ptr_t pv8_ifname);

typedef mv_vptr_t PING_HANDLE;
PING_HANDLE MVAPI mvos_ping_init(mv_s32_t s32_timeout_ms, mv_v8ptr_t pv8_host);
mv_s32_t    MVAPI mvos_ping_host(PING_HANDLE handle, mv_s32_t s32_packet_count);
mv_s32_t    MVAPI mvos_ping_host_with_size(PING_HANDLE handle, mv_s32_t s32_packet_count, mv_s32_t s32_patcket_size);
mv_void_t   MVAPI mvos_ping_uninit(PING_HANDLE handle);
mv_s32_t    MVAPI mvos_ping_host_once(mv_v8_t pv8_host_array[][MVOS_NET_BUFLEN], mv_s32_t s32_host_num, mv_s32_t s32_timeout_ms);

/**
 * @brief 等价封装hton和ntoh系列
 */
#if __BYTE_ORDER__ ==__ORDER_BIG_ENDIAN__
#define mvos_htonl(u32_val) u32_val
#define mvos_htons(u16_val) u16_val
#else
#define mvos_htonl(u32_val) ((((u32_val)&0xff000000)>>24)|(((u32_val)&0x00ff0000)>>8)|(((u32_val)&0x000000ff)<<24)|(((u32_val)&0x0000ff00)<<8))
#define mvos_htons(u16_val) ((((u16_val)&0xff00)>>8)|(((u16_val)&0x00ff)<<8))
#endif
#define mvos_ntohl(u32_val) mvos_htonl(u32_val)
#define mvos_ntohs(u16_val) mvos_htons(u16_val)
/*****************************************
 *  time类时间操作(由mv_time_t做强制64位处理)
 *****************************************/
mv_time_t MVAPI mvos_time        (mv_time_t *p_ts);
mv_time_t MVAPI mvos_time_ms     (mv_time_t *p_ts_ms);
mv_time_t MVAPI mvos_time_us     (mv_time_t *p_ts_us);
mv_time_t MVAPI mvos_time_mono   (mv_time_t *p_ts_mono);
mv_time_t MVAPI mvos_time_mono_ms(mv_time_t *p_ts_mono_ms);
mv_time_t MVAPI mvos_time_mono_us(mv_time_t *p_ts_mono_us);
mv_time_t MVAPI mvos_time_base   (mv_time_t *p_ts);
mv_time_t MVAPI mvos_time_base_ms(mv_time_t *p_ts_ms);
mv_time_t MVAPI mvos_time_base_us(mv_time_t *p_ts_us);
mv_s32_t  MVAPI mvos_stime (mv_time_t *p_ts);
mv_s32_t  MVAPI mvos_settimeofday(mv_time_t ts_sec, mv_time_t ts_usec); ///< 部分平台不支持时会自动处理为stime（仅秒有效）

typedef struct _os_tm
{
    mv_s32_t  sec;        ///< Seconds. [0-60] (1 leap second)
    mv_s32_t  min;        ///< Minutes. [0-59]
    mv_s32_t  hour;       ///< Hours.   [0-23]
    mv_s32_t  mday;       ///< Day.     [1-31]
    mv_s32_t  mon;        ///< Month.   [0-11]
    mv_s32_t  year;       ///< Year - 1900.
    mv_s32_t  wday;       ///< Day of week. [0-6]
    mv_s32_t  yday;       ///< Days in year.[0-365]
    mv_s32_t  isdst;      ///< DST.     [-1/0/1]
    mv_time_t ts_gmtoff;  ///< Seconds east of UTC.
}mvos_tm_t;
mv_s32_t  MVAPI mvos_gmtime(const mv_time_t *p_ts, mvos_tm_t *p_tm);
mv_time_t MVAPI mvos_mktime(const mvos_tm_t *p_tm);
mv_time_t MVAPI mvos_gmtoff();
/**
 * @brief 设置/获取mvos模块内部时区设定值
 * 
 * @param s16_set [in] 时区值 [+hhmm]/[-hhmm]
 * @return 当前时区设定值
 * 
 * @note 并不等价于于设置了系统时区，且仅对mvos_local_localtime有效
 */
mv_s16_t  MVAPI mvos_local_tz(mv_s16_t s16_set);
/**
 * @brief 设置/获取mvos模块内部DST（夏令时）设定值
 * 
 * @param s8_set [in] DST值 [-1, 0, 1, ...]
 * @return mv_s8_t 
 * 
 * @note 并不等价于设置了系统DST，且仅对mvos_local_localtime有效；
 * @note 设置-1时，禁用模块内DST功能; DST值小于-24或大于24时，表示仅获取
 */
mv_s8_t   MVAPI mvos_local_dst(mv_s8_t s8_set);
/**
 * @brief 获取基于mvos模块内部时区的给定时间日期转换
 * 
 * @param p_ts [in]  指定时间戳（可选，NULL时，自动转换当前系统时间戳）
 * @param p_tm [out] 日期结构体缓存
 * @return 日期转换操作结果 
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS (p_tm为空)
 * 
 * @note 并不等价于基于系统时区设置的标准localtime函数
 */
mv_s32_t  MVAPI mvos_local_localtime(const mv_time_t *p_ts, mvos_tm_t *p_tm);

mv_u32_t  MVAPI mvos_sleep (mv_u32_t u32_sec);
mv_u32_t  MVAPI mvos_msleep(mv_u32_t u32_msec);
mv_s32_t  MVAPI mvos_usleep(mv_u32_t u32_usec);
#if 0
/**
 * @brief pthread类操作
 */
#include <pthread.h>
#define MVOS_PTHREAD_STACKSIZE_FACTOR   4
/**
 * @brief 线程创建
 * 
 * @param p_tid            [in] 线程id取出缓存地址（可选）
 * @param __start_routine  [in] 线程函数入口
 * @param av8_pname        [in] 线程自定义名称（可选，NULL为不设置）
 * @param s32_stack_size   [in] 线程栈区域界限大小（可选，0则使用系统默认值）
 * @param p_args           [in] 线程入参参数地址
 * @param s32_arg_copy_len [in] 线程入参影子长度（0：p_args原始地址入参，>0:p_args大小，则表示启用影子参数，线程内操作结果与原始入参无关）
 * @param u8_rr_sch        [in] 线程实时调度等级（可选，0为系统默认；非0则手动指定线程调度优先级）
 * @param u8_detach        [in] 线程分离标识（可选，0为不分离；非0为分离）
 * @return 线程创建操作结果 
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_MALLOC_FAILED
 */
mv_s32_t MVAPI mvos_pthread_create(
    pthread_t   *p_tid,         mv_vptr_t(*__start_routine)(mv_vptr_t),
    mv_v8_t   av8_pname[16], mv_s32_t s32_stack_size,
    mv_vptr_t p_args,        mv_s32_t s32_arg_copy_len,
    mv_u8_t   u8_rr_sch,     mv_u8_t  u8_detach);

mv_s32_t MVAPI mvos_pthread_join(pthread_t tid, mv_void_t **retval);
#endif
/*****************************************
 *               task类操作
 *****************************************/
/**
 * @brief 任务创建（强制分离）
 * 
 * @param __start_routine  [in] 任务函数入口
 * @param av8_pname        [in] 任务自定义名称（可选，NULL为不设置）
 * @param s32_stack_size   [in] 任务栈区域界限大小（可选，0则使用系统默认值）
 * @param p_args           [in] 任务入参参数地址
 * @param s32_arg_copy_len [in] 任务入参影子长度（0：p_args原始地址入参，>0:p_args大小，则表示启用影子参数，线程内操作结果与原始入参无关）
 * @param u8_rr_sch        [in] 任务实时调度等级（可选，0为系统默认；非0则手动指定线程调度优先级）
 * @return 任务创建操作结果 
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_MALLOC_FAILED
 */
mv_s32_t MVAPI mvos_pthread_create(
    mv_vptr_t(*__pth_start_routine)(mv_vptr_t),
    mv_v8_t   av8_pname[16], mv_s32_t s32_stack_size,
    mv_vptr_t p_args,        mv_s32_t s32_arg_copy_len,
    mv_u8_t   u8_rr_sch);
/** 非分离模式创建 */
mv_vptr_t MVAPI mvos_pthread_create_undetach(
    mv_vptr_t(*__pth_start_routine)(mv_vptr_t),
    mv_v8_t   av8_pname[16], mv_s32_t s32_stack_size,
    mv_vptr_t p_args,        mv_s32_t s32_arg_copy_len,
    mv_u8_t   u8_rr_sch);
/**
 * @brief 任务退出等待
 * 
 * @param ptid     [in]  任务ptid（由"mvos_task_create_undetach"返回）
 * @param pretval  [out] 任务返回内存地址
 * @param pts_exit [out] 任务完成时间点（单调sec - mvos_time_mono）
 * @param bl_reuse [in]  是否进入待reuse状态（若MV_FALSE，则会回收剩余的任务资源，不可再用）
 * @param bl_async [in]  退出试探（若MV_TRUE，则任务未退出时，直接返回busy；而非强制等待）
 * @return 等待结果
 * - success : MV_EC_SUCCESS      (已退出) 
 * -  failed : MV_EC_INVALID_ARGS (ptid为NULL)
 *             MV_EC_IGNORE       (非detach的ptid)
 *             MV_EC_ACTION_BUSY  (任务运行中，未完成)
 */
mv_s32_t MVAPI mvos_pthread_join(mv_vptr_t ptid, mv_vptr_t *pretval);
mv_s32_t MVAPI mvos_pthread_join_ex(mv_vptr_t ptid, mv_vptr_t *pretval, mv_time_t *pts_exit, mv_bool_t bl_reuse, mv_bool_t bl_async);
/**
 * @brief 任务复用（任务底层资源复用，避免重复创建销毁；适用于线程池）
 * 
 * @param ptid                [in] 任务ptid（由"mvos_task_create_undetach"返回）
 * @param __pth_start_routine [in] 任务函数入口
 * @param av8_pname           [in] 任务自定义名称（可选，NULL为不设置；不设置则会沿用上一次任务名称）
 * @param p_args              [in] 任务入参参数地址
 * @param s32_arg_copy_len    [in] 任务入参影子长度（0：p_args原始地址入参，>0:p_args大小，则表示启用影子参数，线程内操作结果与原始入参无关）
 * @return  任务创建操作结果 
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS (ptid为NULL)
 *             MV_EC_IGNORE       (非detach的ptid)
 *             MV_EC_NOT_READY    (ptid上一个运行中任务未完成)
 */
mv_s32_t MVAPI mvos_pthread_reuse(
    mv_vptr_t ptid,          
    mv_vptr_t(*__pth_start_routine)(mv_vptr_t), mv_v8_t av8_pname[16], 
    mv_vptr_t p_args, mv_s32_t s32_arg_copy_len);

#if 0 ///< 弃用task类接口
/** pthread类用法兼容接口(仅供代码上兼容替换方便，线程返回值特性无法使用，推荐使用"mvos_pthread_create") */
mv_s32_t MVAPI mvos_task_create(
    mv_void_t(*__tsk_start_routine)(mv_vptr_t),
    mv_v8_t   av8_pname[16], mv_s32_t s32_stack_size,
    mv_vptr_t p_args,        mv_s32_t s32_arg_copy_len,
    mv_u8_t   u8_rr_sch);
/** pthread类非分离模式用法兼容接口 */
mv_vptr_t MVAPI mvos_task_create_undetach(
    mv_void_t(*__tsk_start_routine)(mv_vptr_t),
    mv_v8_t   av8_pname[16], mv_s32_t s32_stack_size,
    mv_vptr_t p_args,        mv_s32_t s32_arg_copy_len,
    mv_u8_t   u8_rr_sch);
/** pthread类非分离模式用法兼容接口 */
mv_s32_t MVAPI mvos_task_join(mv_vptr_t ptid);
#endif

/*****************************************
 *           random随机数据操作
 *****************************************/

/**
 * @brief 随机数据生成
 * 
 * @param pu8_cache [in] 随机数据生成缓存区
 * @param s32_len   [in] 需要生成的数据长度
 * @return 操作结果
 * - success : 实际生成数据长度
 * -  failed : 0
 */
mv_s32_t MVAPI mvos_random_data_generate(mv_u8ptr_t pu8_cache, mv_s32_t s32_len);
mv_s32_t MVAPI mvos_random_data_generate_with_seed(mv_u8ptr_t pu8_cache, mv_s32_t s32_len, mv_u32_t u32_seed); ///< u32_seed非0时生效

/**
 * @brief 指定范围内随机数字生成
 * 
 * @param pu8_cache [in] 随机数字生成缓存区
 * @param s32_len   [in] 需要生成的数字类型长度(1/2/4/8)
 * @param u64_min   [in] 最小值
 * @param u64_max   [in] 最大值
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_FAILED
 * @note 指定范围取闭区间，如 [1,3] => 1,2,3 内随机 \n
 *       最大支持64位数据，需要取负数时，自行对结果取负处理即可
 */
mv_s32_t MVAPI mvos_random_number_generate(mv_u8ptr_t pu8_cache, mv_s32_t s32_len, mv_u64_t u64_min, mv_u64_t u64_max);
/**
 * @brief 随机可见字符串生成
 * 
 * @param pv8_cache [in] 随机字符串生成缓存区
 * @param s32_len   [in] 需要生成的数据长度
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_FAILED
 */
mv_s32_t MVAPI mvos_random_string_generate(mv_v8ptr_t pv8_cache, mv_s32_t s32_len);
/**
 * @brief 数据映射
 * 
 * @param pu8_data   [in/out] 需要映射的数据缓冲区
 * @param s32_len    [in]     数据长度
 * @param cpu8_table [in]     映射表
 * @param s32_tbsize [in]     映射表大小
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : else
 * @note 根据映射表大小，对映射数据取余作为下标查表转换
 * @note 可以用来配合 mvos_random_data_generate 实现指定表内数据随机结果
 */
mv_s32_t MVAPI mvos_data_mapping(mv_u8ptr_t pu8_data, mv_s32_t s32_len, mv_u8ptr_t cpu8_table, mv_s32_t s32_table_size);
/*****************************************
 *             string类操作
 *****************************************/
#define MVOS_STR_CASE_LOWER  0
#define MVOS_STR_CASE_UPPER  1
mv_size_t  MVAPI mvos_strlen (mv_cv8ptr_t cpv8_string);
mv_v8ptr_t MVAPI mvos_strdup (mv_cv8ptr_t cpv8_src, mv_off_t offset,         mv_size_t sz_cnt);     ///< sz_cnt=0时，为全字符串复制；（本接口成功调用会申请新的内存，需要调用者自行管理释放）
mv_v8ptr_t MVAPI mvos_strncpy(mv_v8ptr_t   pv8_dst, mv_cv8ptr_t cpv8_src,    mv_size_t sz_cnt);
mv_s32_t   MVAPI mvos_strncmp(mv_cv8ptr_t cpv8_dst, mv_cv8ptr_t cpv8_src,    mv_size_t sz_cnt);     ///< sz_cnt=0时，为无限比较模式
mv_v8ptr_t MVAPI mvos_strstr (mv_cv8ptr_t cpv8_dst, mv_cv8ptr_t cpv8_needle, mv_size_t sz_cnt);     ///< sz_cnt=0时，为无限查找模式
mv_v8ptr_t MVAPI mvos_strrstr(mv_cv8ptr_t cpv8_dst, mv_cv8ptr_t cpv8_needle, mv_size_t sz_cnt);     ///< 同上，返回匹配结尾首地址
mv_bool_t  MVAPI mvos_strendwith (mv_cv8ptr_t cpv8_dst, mv_cv8ptr_t cpv8_needle, mv_size_t sz_cnt); ///< sz_cnt=0时，为无限查找模式
mv_v8ptr_t MVAPI mvos_strcase(mv_v8ptr_t   pv8_string, mv_size_t sz_cnt, mv_u8_t u8_str_case);
mv_s32_t   MVAPI mvos_strcasencmp(mv_cv8ptr_t cpv8_dst, mv_cv8ptr_t cpv8_src,    mv_size_t sz_cnt);  ///< sz_cnt=0时，为无限比较模式(忽略大小写)
mv_ssize_t MVAPI mvos_strdrop(mv_v8ptr_t pv8_dst, mv_cv8ptr_t cpv8_src, mv_cv8ptr_t cpv8_charset, mv_size_t sz_cnt); ///< 丢弃string内与charset任一字符相同的内容
/***********/
mv_bool_t  MVAPI mvos_strisdigit(mv_cv8ptr_t cpv8_string, mv_size_t sz_cnt);      ///< 是否全数字字符串(sz_cnt=0时，全长)
mv_s64_t   MVAPI mvos_str2integer_scal_uom(mv_cv8ptr_t cpv8_string, mv_u8_t u8_scal, mv_bool_t bl_with_unit_of_measure); ///< 字符串(2/8/10/16进制)转整数
mv_s64_t   MVAPI mvos_str2integer_uom(mv_cv8ptr_t cpv8_string, mv_bool_t bl_with_unit_of_measure); ///< 字符串(十进制)转整数(可选是否判断紧跟的数据量级单位"B/K/M/G/T/P")
#define mvos_str2integer_scal(str, scal) mvos_str2integer_scal_uom(str, scal, MV_FALSE) ///< 兼容旧接口调用方式
#define mvos_str2integer(str) mvos_str2integer_uom(str, MV_FALSE) ///< 兼容旧接口调用方式
mv_f64_t   MVAPI mvos_str2double (mv_cv8ptr_t cpv8_string); ///< 字符串转浮点数
/***********/
#define MVOS_INT2STR_BUF_SIZE_MIN  4
typedef enum _style
{
    MVOS_INT2STR_STYLE_NONE          = 0,
    MVOS_INT2STR_STYLE_SPACEPAD      = 0x20,   ///< 常用' '占位符格式化（优先级低于前缀和符号位）
    MVOS_INT2STR_STYLE_ZEROPAD       = 0x30,   ///< 常用补'0'格式（优先级高于前缀和符号位）
#define MVOS_INT2STR_STYLE_PADCHAR_MIN 0x20
#define MVOS_INT2STR_STYLE_PADCHAR_MAX 0x7e 
    MVOS_INT2STR_STYLE_PADCHAR_MASK  = 0xff,   ///< 特殊支持任意字符pading（优先级低于前缀和符号位）
    MVOS_INT2STR_STYLE_64BIT         = 0x100,
    MVOS_INT2STR_STYLE_32BIT         = 0x200,
    MVOS_INT2STR_STYLE_16BIT         = 0x300,
    MVOS_INT2STR_STYLE_8BIT          = 0x400,
    MVOS_INT2STR_STYLE_BITMASK       = 0xf00,  ///< 类型单选；主要针对负数数值转16和8进制反码补位数量限制(不指定，则默认按32补)
    MVOS_INT2STR_STYLE_UPPER         = 0x1000,
    MVOS_INT2STR_STYLE_PREFIX        = 0x2000,
    MVOS_INT2STR_STYLE_PAD_PRYRVS    = 0x4000, ///< 优先级反转padding（'0'变为低优先级，其他字符变为高优先级)
    MVOS_INT2STR_STYLE_FUNCMASK      = 0xf000, ///< 功能多选；
}mvos_int2str_style_bmpc_e;
/**
 * @brief 整数转字符串功能（支持多种scal）
 * 
 * @param s64_value      [in] 目标转换整数，最大支持s64
 * @param pv8_buf        [in] 转换输出buffer
 * @param u8_max         [in] 输出buffer缓冲区大小
 * @param u8_scal        [in] 转换进制选择（16、10、8、2）
 * @param u16_style      [in] 转换风格[mvos_int2str_style_bmpc_e]
 * @param u8_padding_len [in] 需要padding目标长度
 * @return 输出字符串起始地址 
 *
 * @note buffer长度，需要预留'\0'位置，函数会自动吧最后一个字节用做结束符保证字符串能完整输出
 *       一般64位数值，普通转换（包含前缀添加），参考buffer长度64字节足够；如果要转换2进制，则最好用80以上字节（最大值为64个1，加上前缀、结束符、padding啥的）
 *       一般32位数值，普通转换（包含前缀添加），参考buffer长度32字节足够；如果要转换2进制，则最好用48以上字节（最大值为32个1，加上前缀、结束符、padding啥的）
 *       其他位数数值类推，按实际需要预留buffer大小
 */
mv_v8ptr_t MVAPI mvos_integer2str_scal(mv_s64_t s64_value, mv_v8ptr_t pv8_buf, mv_u8_t u8_max, mv_u8_t u8_scal, mv_u16_t u16_style, mv_u8_t u8_padding_len);

/***********/
mv_void_t  MVAPI mvos_hex2str(mv_v8ptr_t pv8_dst, mv_cu8ptr_t cpu8_digest, mv_s32_t s32_len, mv_u8_t u8_str_case); ///< 十六进制串转字符串(可选大小写)
mv_void_t  MVAPI mvos_str2hex(mv_u8ptr_t pu8_dst, mv_cv8ptr_t cpv8_digest, mv_s32_t s32_len); ///< 字符串转十六进制串
/***********/
/**
 * MVOS_VA64: 为了在某些特殊不支持原生64位的系统或编译器上使用64位变参，
 *            mvos_printf和mvos_snprintf接口的64位入参，均强烈建议使用此宏套封装
 */
#ifdef MV_VA_ARG_SPEC_ALIGN_64
typedef union {mv_u64_t v;struct {mv_u32_t h; mv_u32_t l;};} mv_va64_t;
#define MVOS_VA64(arg64) (mv_va64_t){arg64}.h, (mv_va64_t){arg64}.l
#else
#define MVOS_VA64(arg64) arg64
#endif
/**
 * @brief 字符串格式化分割
 * 
 * @param pv8_string [in]目标操作字符串（必须可写，会进行数据更改）
 * @param pv8_fmt    [in]分割格式（单'*'代表内容块，其他字符代表分割符; 双"**"转义表示一个*的普通分隔符）
 * @param s32_argnum [in]内容提取指针地址入参数量
 * @param ...        [in]内容提取指针地址（可变数量参）
 * @return 操作结果 
 * - success : 最后一个找到的分隔符所在偏移量+1(0=未找到分割符)
 * -  failed : MV_EC_INVALID_ARGS
 * @note 不需要的内容块，可以像下面例子代码一样，使用连续的分隔符进行跳过操作
 * @note 单'*'标记，对应入参为NULL也能达到相同的跳过效果
 * @code
    int main(void)
    {
    #define ORI_DATA "test:abc^444^^13456098;noneed&noneed2&pppppp_ss"
    #define DATA_FMT "*:*^*^*^*;&*&*"
        char data[1024] = {ORI_DATA};
        char *fmt       = DATA_FMT;
        char *p1 = NULL; *p2 = NULL; *p3 = NULL;
        char *p4 = NULL; *p5 = NULL; *p6 = NULL;
        mvcom_sstr_scan(data, fmt, &p1, &p2, &p3, &p4, &p5, NULL, &p6);
        printf(
            "=======================\n"
            "%s\n"
            "=======================\n"
            "%s\n%s\n%s\n%s\n%s\n%s\n"
            "=======================\n",
            ORI_DATA,
            p1, p2, p3, p4, p5, p6
        );
        return 0;
    }
 * @endcode
 */
mv_s32_t MVAPI mvos_strscan_s(mv_v8ptr_t pv8_string, mv_v8ptr_t pv8_fmt, mv_s32_t s32_argnum, ...);
/**
 * @brief 一般使用此宏，可自动计算变参入参数量
 */
#define mvos_strscan(str, fmt, ...) mvos_strscan_s((str), (fmt), MV_ARG_COUNT(__VA_ARGS__), ##__VA_ARGS__)
/**
 * @brief 字符串格式化拼接
 * 
 * @param ppv8_cache [in] 拼接内容缓存地址指针
 * @param sz_maxlen  [in] 拼接内容缓存地址最大容量
 * @param cpv8_fmt   [in] 拼接格式
 * @param argnum     [in] 拼接内容入参数量
 * @param ...        [in] 拼接内容可变数量参
 * @return 格式化拼接结果
 * - success : >0 格式化填充数据长度 (格式化操作的特殊性)
 * -  failed : MV_EC_INVALID_ARGS (ppv8_cache为NULL异常) <br/>
 *             MV_EC_MALLOC_FAILED(内存不足，【智能内存申请】时) <br/>
 *             MV_EC_OUT_OF_RANGE (超过maxlen,可用内存部分已写入)
 * @note ppv8_cache入参实体指向可以为NULL,且sz_maxlen为0时，代表启用【智能内存申请】机制， <br/>
 *       自动申请满足的缓存长度内容，并赋值ppv8_cache出参; <br/>
 *         e.g. mv_vptr_t p = NULL; mvos_snprintf_s(&p, 0, ...); <br/>
 *       sz_maxlen为非0时，代表普通模式，ppv8_cache应为实体地址，使用(mv_v8ptr_t*)方式进行异变传参，以符合调用方法； <br/>
 *         e.g. mv_v8_t av8_buf[16] = {0}; mvos_snprintf_s((mv_v8ptr_t*)av8_buf, 16, ...);， <br/>
 * @note 使用【智能内存申请】机制后，调用者须在不再需要使用的时候，自行释放该内存块，避免内存泄露！
 */
mv_s32_t MVAPI mvos_snprintf_s(mv_v8ptr_t *ppv8_cache, mv_size_t sz_maxlen, mv_cv8ptr_t cpv8_fmt, mv_s32_t argnum, ...);
/** 方便部分需要vsnprintf二次封装的地方调用(valist) */
#include <stdarg.h>
mv_s32_t MVAPI mvos_vsnprintf_s(mv_v8ptr_t __restrict pv8_cache, mv_size_t sz_maxlen, mv_cv8ptr_t cpv8_fmt, va_list valist);
/**
 * @brief 一般使用此宏，可自动计算变参入参数量
 */
#define  mvos_snprintf(ppv8_cache, sz_maxlen, cfmt, ...) mvos_snprintf_s((mv_v8ptr_t*)(ppv8_cache), sz_maxlen, (cfmt), MV_ARG_COUNT(__VA_ARGS__), ##__VA_ARGS__)
/**
 * @brief 字符串格式化输出(stdout)
 * 
 * @param cpv8_fmt   [in] 输出格式
 * @param argnum     [in] 输出内容入参数量
 * @param ...        [in] 输出内容可变数量参
 * @return 格式化输出结果
 * - success : >0 格式化输出数据长度
 * -  failed : MV_EC_IGNORE <br/>
 *             MV_EC_MALLOC_FAILED
 */
mv_s32_t MVAPI mvos_printf_s(mv_cv8ptr_t cpv8_fmt, mv_s32_t argnum, ...);
#define  mvos_printf(cfmt, ...) mvos_printf_s((cfmt), MV_ARG_COUNT(__VA_ARGS__), ##__VA_ARGS__)

/*****************************************
 *         data debug 类封装
 ****************************************/
#define mvos_dbg_mem_print_val(member) mvos_printf("[%s][l:%d]"#member": %lld\n", __func__, __LINE__, MVOS_VA64((mv_s64_t){member}));
#define mvos_dbg_mem_print_hex(member, cnt) {mv_s32_t i = 0; mvos_printf("[%s][l:%d]"#member": \n", __func__, __LINE__); for(i=0;i<cnt; i++) {if((i>0)&&(0==(i%16))){mvos_printf("\n");} mvos_printf("%02X ", ((mv_u8ptr_t)member)[i]);} mvos_printf("\n");}
#define mvos_dbg_mem_print_hexdump(member, cnt) {\
mv_s32_t i = 0, j = 0, empty = cnt%16; \
mvos_printf("[%s][l:%d]"#member": \n", __func__, __LINE__); \
    for(i=0;i<=cnt;i++) {\
        if((i>0)&&(0==(i%16))){\
            mvos_printf("   "); \
            for(;j<i; j++) { \
                mvos_printf("%c ", ((((mv_u8ptr_t)member)[j]>0x7E)||(((mv_u8ptr_t)member)[j]<0x20))?'.':((mv_u8ptr_t)member)[j]); \
            } \
            mvos_printf("\n"); \
            if (i==cnt){break;}\
        } \
        mvos_printf("%02X ", ((mv_u8ptr_t)member)[i]); \
    } \
    if (empty > 0) { \
        for(;empty<16;empty++) {\
            mvos_printf("   "); \
        } \
        if(j<cnt){ \
            mvos_printf("   "); \
            for(;j<cnt; j++) { \
                mvos_printf("%c ", ((((mv_u8ptr_t)member)[j]>0x7E)||(((mv_u8ptr_t)member)[j]<0x20))?'.':((mv_u8ptr_t)member)[j]); \
            } \
        } \
    } \
    mvos_printf("\n"); \
}
#define mvos_dbg_mem_print_chr(member, cnt) {mv_s32_t i = 0; mvos_printf("[%s][l:%d]"#member": ", __func__, __LINE__); for(i=0;i<cnt; i++) {mvos_printf("%c", ((mv_u8ptr_t)member)[i]);} mvos_printf("\n");}
#define mvos_dbg_printf(cfmt, ...) mvos_printf_s("[%s][l:%d]"cfmt, MV_ARG_COUNT(__VA_ARGS__)+2, __func__, __LINE__, ##__VA_ARGS__)
/*****************************************
 *             memory类操作
 *****************************************/
mv_vptr_t MVAPI mvos_malloc (mv_size_t size);
mv_vptr_t MVAPI mvos_zalloc (mv_size_t size);                    ///< zero malloc
mv_vptr_t MVAPI mvos_realloc(mv_vptr_t p_old, mv_size_t size);
mv_vptr_t MVAPI mvos_memdup (mv_cvptr_t cp_src, mv_size_t size); ///< 复制一份目标内存长度的内存块及内容
mv_void_t MVAPI mvos_free   (mv_vptr_t p);
mv_vptr_t MVAPI mvos_memset (mv_vptr_t p,      mv_v8_t v8_val,   mv_size_t cnt);
mv_s32_t  MVAPI mvos_memcmp (mv_cvptr_t p1,    mv_cvptr_t p2,    mv_size_t cnt);
mv_vptr_t MVAPI mvos_memcpy (mv_vptr_t p_dst,  mv_cvptr_t p_src, mv_size_t cnt);
mv_vptr_t MVAPI mvos_memmov (mv_vptr_t p_dst,  mv_cvptr_t p_src, mv_size_t cnt);

/*****************************************
 *             sem 类操作
 *****************************************/
typedef mv_vptr_t mvos_sem_t;

#define MVOS_SEM_INIT(name, val)                                \
    static mvos_sem_t name##_sem = NULL;                        \
    __attribute__((constructor))                                \
    static mv_void_t name##_sem_init_auto()                     \
    {                                                           \
        mv_s32_t _s32_retval = mvos_sem_init(&name##_sem, val); \
        if(_s32_retval != MV_EC_SUCCESS) {                      \
            printf("%s sem init failed \n", #name);             \
        }                                                       \
    }                                                           \
                                                                \
    __attribute__((destructor))                                 \
    static mv_void_t name##_sem_uninit_auto()                   \
    {                                                           \
        mv_s32_t _s32_retval = mvos_sem_uninit(&name##_sem);    \
        if(_s32_retval != MV_EC_SUCCESS) {                      \
            printf("%s sem uninit failed \n", #name);           \
        }                                                       \
    }

mv_s32_t MVAPI mvos_sem_init     (mvos_sem_t *sem, mv_s32_t s32_def_val);
mv_s32_t MVAPI mvos_sem_uninit   (mvos_sem_t *sem);
mv_s32_t MVAPI mvos_sem_post     (mvos_sem_t *sem);
mv_s32_t MVAPI mvos_sem_wait     (mvos_sem_t *sem);
mv_s32_t MVAPI mvos_sem_trywait  (mvos_sem_t *sem);
mv_s32_t MVAPI mvos_sem_timedwait(mvos_sem_t *sem, mv_s32_t timeout_ms);
mv_s32_t MVAPI mvos_sem_getvalue (mvos_sem_t *sem, mv_s32ptr_t ps32_sem_val);

/*****************************************
 *             mutex 类操作
 *****************************************/

typedef mv_vptr_t mvos_mutex_t;

#define MVOS_MUTEX_INIT(name)                                   \
    static mvos_mutex_t name##_mutex = NULL;                    \
    __attribute__((constructor))                                \
    static mv_void_t name##_mutex_init_auto()                   \
    {                                                           \
        mv_s32_t _s32_retval = mvos_mutex_init(&name##_mutex);  \
        if(_s32_retval != MV_EC_SUCCESS) {                      \
            mvos_printf("%s mutex init failed \n", #name);      \
        }                                                       \
    }                                                           \
                                                                \
    __attribute__((destructor))                                 \
    static mv_void_t name##_mutex_uninit_auto()                 \
    {                                                           \
        mv_s32_t _s32_retval = mvos_mutex_uninit(&name##_mutex);\
        if(_s32_retval != MV_EC_SUCCESS) {                      \
            mvos_printf("%s mutex uninit failed \n", #name);    \
        }                                                       \
    }

mv_s32_t MVAPI mvos_mutex_init     (mvos_mutex_t *mutex);
mv_s32_t MVAPI mvos_mutex_uninit   (mvos_mutex_t *mutex);
mv_s32_t MVAPI mvos_mutex_lock     (mvos_mutex_t *mutex);
mv_s32_t MVAPI mvos_mutex_unlock   (mvos_mutex_t *mutex);
mv_s32_t MVAPI mvos_mutex_timedlock(mvos_mutex_t *mutex, mv_s32_t timeout_ms);
mv_s32_t MVAPI mvos_mutex_trylock  (mvos_mutex_t *mutex);

MVCXX_EXTERN_END

#endif
